package org.goldenport.g3.adapters

import org.goldenport.util.QSymbol
import org.goldenport.g3._
import org.goldenport.g3.messages._
import org.goldenport.g3.messages.query.{RecordQuery, RootContext}
import org.goldenport.g3.messages.view._
import org.goldenport.g3.events.{Exceptioned, RecordFetched, RecordQueried}
import org.goldenport.g3.events.entity._
import org.goldenport.g3.events.view._

/**
 * @since   Aug. 27, 2010
 * @version Oct.  5, 2010
 * @author  ASAMI, Tomoharu
 */
class ViewAdapter(val driver: G3ViewDriver) extends G3Adapter {
  override def open_Adapter() {
    driver.open(context)
  }

  override def close_Adapter() {
    driver.close()
  }

  override protected def do_Action(content: AnyRef, parcel: G3Parcel, ctx: G3AgentContext): AnyRef = {
    content match {
      case cmd: G3Command => driver.execute(cmd, ctx)
    }
  }
}

abstract class G3ViewDriver extends G3Driver {
  protected def new_Agent(cmd: G3Command, ctx: G3AgentContext): G3ViewDriverAgent
}

abstract class G3ViewDriverAgent(uri: String, context: G3AgentContext) extends G3DriverAgent(uri, context) with UseRecord {
  val result: RecordQuery

  agent {
    case cmd: FetchView => fetch(cmd)
    case cmd: QueryView => query(cmd)
    case cmd: QueryViewExpression => query(cmd)
  }

  def fetch(msg: FetchView): G3Event = {
    fetchTx(msg) match {
      case e: Exceptioned => e
      case evt: RecordFetched => new ViewFetched(uri, msg, evt.records, Some(evt))
      case evt: RecordQueried => new ViewFetched(uri, msg, evt.records, Some(evt))
    }
  }

  def fetchTx(msg: FetchView): G3Event

  def query(msg: QueryView): G3Event = {
    queryTx(msg) match {
      case e: Exceptioned => e
      case evt: RecordQueried => new ViewQueried(uri, msg, evt.records, Some(evt))
    }
  }

  def queryTx(msg: QueryView): G3Event 

  def query(msg: QueryViewExpression): G3Event

  def get(get: Get): G3Event = {
    error("")
  }

  def post(post: Post): G3Event = {
    error("")
  }

  def put(put: Put): G3Event = {
    error("")
  }

  def delete(delete: Delete): G3Event = {
    error("")
  }

  def mkcol(mkcol: Mkcol): G3Event = {
    error("")
  }
}

abstract class G3DataStoreViewDriverAgent(val datastoreUri: String, context: G3AgentContext) extends G3ViewDriverAgent(datastoreUri, context) {
  lazy val dsdriver = context.createDataStoreDriver(datastoreUri)

  override def open() {
    dsdriver.open(context.context)
  }

  override def close() {
  }

  def fetchTx(msg: FetchView): G3Event = {
    val q = make_fetch_query(msg.ids)
    dsdriver.execute(datastore.Query(q), context)
  }

  private def make_fetch_query(ids: List[AnyRef]): RecordQuery = {
    val ctx = new RootContext()
    ctx.setIds(ids)
    result.normalize(ctx)
  }

  def queryTx(msg: QueryView): G3Event = {
    dsdriver.execute(datastore.Query(msg.query), context)
  }

  def query(msg: QueryViewExpression): G3Event = {
    error("XXX")
  }
}

abstract class G3EntityViewDriverAgent(val driver: G3EntityDriver, context: G3AgentContext) extends G3ViewDriverAgent("XXX:G3EntityViewDriverAgent", context) with UseRecord {
  val entityName: QSymbol

  override def open() {
    driver.open(context.context)
  }

  override def close() {
  }

  def fetchTx(msg: FetchView): G3Event = {
    val q = make_fetch_query(msg.ids)
    driver.execute(entity.Query(q), context)
  }

  private def make_fetch_query(ids: List[AnyRef]): RecordQuery = {
    val ctx = new RootContext()
    ctx.setIds(ids)
    result.normalize(ctx)
  }

  def queryTx(msg: QueryView): G3Event = {
    driver.execute(entity.Query(msg.query), context)
  }

  def query(msg: QueryViewExpression): G3Event = {
    driver.execute(entity.Query(msg.uri, msg.expression), context)
  }
}
